<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  迭代器， 生成器， promise， async, await

  迭代和遍历有什么区别？
  迭代：从目标源逐个抽取的方式提取数据

  1.异步; 防止DOM冲突，js设置成单线程
  2.事件轮询
  3.回调函数

  1.因为JS是单线程，解决方式异步
  2.异步解决方案是 事件轮询event loop
  3.时间轮询的核心是--回调函数
  <!-- 高阶函数：参数是回调函数 -->
  arr.sort(function(a, b) {

  })

  setTimeout(function() {

  }, 3000)





  <script>
    // 迭代器

    // Array, Map, Set, String, TypeArray, arguments
    // 为了对以上数据提供统一的遍历方法

    // var arr = [1, 2, 3, 4]
    // var str = '123'
    // var obj = {
    //   a: 1,
    //   b: 2
    // }

    // console.log(arr);
    // console.log(str);
    // console.log(obj);

    // arr, str 原型都有Symbol.iterator方法，所以可以使用for...of 进行迭代
    // 他的返回值是一个迭代器对象
    // iter = arr[Symbol.iterator]()
    // console.log(iter);
    // 迭代器对象上有next对象
    // console.log(iter.next()); // value; done
    // console.log(iter.next());
    // console.log(iter.next());
    // console.log(iter.next());
    // console.log(iter.next());

    // 手撕iterator原方法 增加记忆
    /*
    function makeIterator(arr) {
      var index = 0
      return {
        next() {
          if (index < arr.length) {
            return {
              value: arr[index++],
              done: false
            }
          }
          return {value: undefined, done: true}
        }
      }
    }
    */

    // let iter2 = makeIterator(arr)
    // console.log(iter2.next());
    // console.log(iter2.next());
    // console.log(iter2.next());
    // console.log(iter2.next());
    // console.log(iter2.next());

    // ******************分割线**********************************

    // Generator
    // yield有中断执行的功能
    /*
    function* test() {
      // console.log(1);
      let v1 = yield 1;
      console.log(v1);
      let v2 = yield 2;
      console.log(v2);
      yield 3;
    }

    let iter = test();
    console.log(iter.next('one'));
    console.log(iter.next('two'));
    console.log(iter.next('three'));

    var obj = {
      a: 1,
      b: 2,
      c: 3,
      [Symbol.iterator]: function* () {
        var index = 0
        let map = new Map()
        map.set('a', 1)
        map.set('b', 2)
        map.set('c', 3)

        var mapEntries = [...map.entries()]
        while (index < mapEntries.length) {
          yield mapEntries[index++]
        }
      }
    }

    for (const i of obj) {
      console.log(i);
    }

    */

    // ******************分割线**********************************

    // Promise (解决回调地狱问题)
    /**
      异步任务的完成与否 取决于当前promise的状态
      三个状态
      pending 进行中
      fulfilled 已完成
      rejected 已失败
    */
    /* 
    let err = false

    function test() {
      // 执行器函数 
      return new Promise(function (resolve, reject) {
        if (err) {
          console.log(1);
          reject(err)
        }
        resolve(data)
      })
    }
    let promise = test()

    promise.then(function (data) {
      console.log("success")
    }, function (err) {
      console.log('err')
    }); 
    */

    /* 
      Promise 连个特性
      1.promise状态不受外界影响
      2.promise的固化；一旦promise状态改变后就不可以在更改
    */

    //微任务队列 异步队列
    // 执行器函数中是宏任务
    // resolve是微任务
    // setTimeout是异步任务
    // 宏任务 -》 微任务 -》 异步任务
    /* 
    let promise = new Promise(function (resolve, reject) {
      console.log('promise');
      resolve('resolve')
    })

    setTimeout(function () {
      console.log('timeout');
    })
    promise.then(function (data) {
      console.log(data);
    })
    console.log('hi');
 */

    // ******************分割线**********************************

    /* 
      Promise.resolve()
      Promise.reject()

      thenable对象
    */
    // 直接返回一个成功态/失败态的promise
    /*
    let p1 = Promise.resolve(1)
    let p2 = Promise.reject(2)
     
        p1.then(function(data) {
          console.log(data);
        })

        p2.catch(function(err) {
          console.log(err);
        })
     */

    // thenable对象
    /* 
    let obj = {
      then(resolve, reject) {
        // resolve(12)
        reject(12)
      }
    }

    // Promise.reject(obj) 无效 通过then函数中的参数改变状态
    let p1 = Promise.resolve(obj)
    p1.then(function(data) {
      console.log(data);
    }, function(err) {
      console.log('err'+err);
    })
 */

    //  练习题
    /* 
    Promise.resolve().then(function () {
      console.log('promise1');
      setTimeout(() => {
        console.log('setTimeout2');
      }, 0)
    })

    setTimeout(() => {
      console.log('setTimeout1');
      Promise.resolve().then(function () {
        console.log('promise2');
      })
    }, 0)
 */
    // ******************分割线**********************************
    /* 
        // Promise链式调用
        let p1 = new Promise((resolve, reject) => {
          setTimeout(() => {
            resolve(10)
          }, 500)
        })
        // 返回值会被Promise.solve(res)包装成promise对象 所以可以链式调用
        // 一样满足状态不可逆原则
        // 链式调用上所有reject 都会被catch捕获
        p1.then(res => {
            console.log(res + 1);
            return res + 1
          })
          .then(res => {
            console.log(res + 1);
            return res + 1
          })
          .then(res => {
            console.log(res + 1);
            return res + 1
          })
     */
    // ******************分割线**********************************

    /* 
      Promise.all()
      Promise.race()
    */
    //  Promise.all() 拿到所有promise值 其中有一个reject都会报错
    //  Promise.race() 拿到最新执行的promise，reject最先可以以被catch到
    /*   
        let p1 = new Promise((resolve, reject) => {
          setTimeout(() => {
            resolve(10)
          }, 1000)
        })

        let p2 = new Promise((resolve, reject) => {
          setTimeout(() => {
            resolve(20)
          }, 2000)
        })

        let p3 = new Promise((resolve, reject) => {
          setTimeout(() => {
            resolve(30)
          }, 3000)
        })

        // let p4 = Promise.all([p1, p2 ,p3])
        let p4 = Promise.race([p1, p2 ,p3])

        p4.then(res => {
          console.log(res); // [10, 20, 30]
          
        })
     */

    // Promise面试题

    // 1.promise状态问题
    /* 
    Promise.resolve()
      .then(() => {
        return new Error('error!!!') // 本质上还是Promise.resolve包装一个状态 走成功
        throw new Error('error') // 才会走失败
      })
      .then((res) => {
        console.log('then:', res);
      })
      .catch((err) => {
        console.log('catch:', err);
      })
 */

    // 2.promise状态固化
    /* 
    const promise = new Promise((resolve, reject) => {
      resolve('success1')
      reject('reject')
      resolve('success2')
    })

    promise.then((res) => {
      console.log('then:', res);
    }).catch((err) => {
      console.log('catch:', err);
    })
 */

    // 3.同步 异步 微任务 1 2 4 3
    /* 
    const promise = new Promise((resolve, reject) => {
      console.log(1);
      resolve()
      console.log(2);
    })
    promise.then((res) => {
      console.log(3);
    })
    console.log(4);
 */

    // 4.普通值会被包装成Promise.resolve()
    /* 
        let p1 = new Promise((resolve, reject) => {
          reject(42)
        })
        p1.catch(function(value) {
          console.log(value); // 42
          return value + 1 // 普通值会被包装成Promise.resolve()
        }).then(function(value) {
          console.log(value); // 43
        })
     */

    // 5.
    /* 
    let p1 = new Promise(function(resolve, reject) {
      resolve(42)
    });
    let p2 = new Promise(function(resolve, reject) {
      reject(43)
    });

    p1.then(function (value) {
      console.log(value);  // 42
      return p2
    }).then(function(value) {
      console.log(value); // 不执行
    })
 */

    // 6.
    /* 
    setTimeout(() => {
      console.log('timer1');  // 2
      Promise.resolve().then(() => {
        console.log('promise1');  // 3
      })
    })

    Promise.resolve().then(() => {
      console.log('promise2');  // 1
      setTimeout(() => {
        console.log('timer2'); // 4
      })
    })
 */


    // 7. 1 3 2
    /* 
    Promise.resolve()
      .then(() => {
        Promise.resolve().then(() => {
          console.log(1);
        }).then(() => {
          console.log(2);
        }) // 没有return 但是会返回Promise.resolve(undefined)
      })
      .then(() => {
        console.log(3);
      })
 */

    // 8.
    /* 
    async function async1() {
      await async2()
      console.log('async1 end');  // 3 async2 return成功的promise所以可以执行 
    }
    // 没有await看成普通函数
    async function async2() {
      console.log('async2 end'); // 1
      // return Promise.reject(new Error()) // 返回失败 "async1 end"则不执行
    }
    async1();
    console.log(10);  // 2
 */

    // 9.
    /* 
    async function async1() {
      await async2()
      console.log('async1'); // 3 async2 return成功的promise所以可以执行 
      await async3();
      console.log('async3'); // 4
    }

    async function async2() {
      console.log('async2'); // 1
      // return Promise.reject(new Error()) // 返回失败 "async1 end"则不执行
    }

    async function async3() {     
      setTimeout(() => {
        console.log('async3 end'); // 5
      })
    }

    async1();
    console.log(10); // 2
 */

    // 10.
    /* 
        console.log('start'); // 1
        async function async1() {
          await async2()
          console.log('async1 end'); // 5
        }
        async function async2() {
          console.log('async2 end'); // 2
        }
        async1()
        setTimeout(function () {
          console.log('setTimeout'); // 8
        })
        new Promise(resolve => {
            console.log('Promise'); // 3
            resolve();
          })
          .then(() => {
            console.log('promise1'); // 6
          })
          .then(() => {
            console.log('promise2'); // 7
          })
        console.log('script end'); // 4
     */

    // 11.(快手)
    let a;
    const b = new Promise((resolve, reject) => {
      console.log('promise1'); // 1
      resolve();
    }).then(() => {
      console.log('promise2'); // 4
    }).then(() => {
      console.log('promise3'); // 5
    }).then(() => {
      console.log('promise4'); // 6
    })

    a= new Promise(async (resolve, reject) => {
      console.log(a); // undefined 2
      await b; // 会等then全部执行完 返回最后一个then结果
      console.log(a); // Promise(pending) 7
      console.log('after1'); // 8
      await a; // 因为Promise(pending) 所以后面代码都是不执行的
      resolve(true);
      console.log('after2');
    });

    console.log('end'); // 3

  </script>
</body>

</html>